package ling

import (
	"gitee.com/tietang/terrace-go/v2/lib/tollgate/handler"
	_go "gitee.com/tietang/terrace-go/v2/lib/tollgate/handler/go"
	"gitee.com/tietang/terrace-go/v2/lib/tollgate/handler/jvm"
	"time"
)

type ProcessMonitor struct {
	ProcessHandlers map[string]handler.ProcessHandler
}

func NewProcessMonitor() *ProcessMonitor {
	pm := &ProcessMonitor{
		ProcessHandlers: make(map[string]handler.ProcessHandler, 0),
	}
	pm.ProcessHandlers["JVM"] = &jvm.JvmProcessHandler{}
	pm.ProcessHandlers["GO"] = &_go.GoProcessHandler{}
	return pm
}

func (p *ProcessMonitor) AllSpecifiedProcesses() []*handler.ServiceProcess {
	pss := make([]*handler.ServiceProcess, 0)
	for _, ph := range p.ProcessHandlers {
		spss, err := ph.GetProcesses()
		if err == nil {
			pss = append(pss, spss...)
		}
	}
	return pss
}

func (p *ProcessMonitor) Watch(fn func(nps, dps []*handler.ServiceProcess)) {
	ticker := time.NewTicker(3 * time.Second)
	for {
		<-ticker.C
		//当前所有的规范进程
		pss := p.AllSpecifiedProcesses()
		//新增的进程
		nps := make([]*handler.ServiceProcess, 0)
		//过滤出新增加的进程
		for _, ps := range pss {
			key := ps.Key()
			if _, ok := lastProcesses[key]; !ok {
				lastProcesses[key] = ps
				nps = append(nps, ps)
			}
		}
		//删除终止的进程
		dps := make([]*handler.ServiceProcess, 0)
		for key, eps := range lastProcesses {
			isExists := false
			pid := eps.Pid
			for _, ps := range pss {
				//如果pid和ppid，serviceID一样，则认为是同一个进程
				isPidEquals := pid == ps.Pid && ps.PPid == eps.PPid
				isPSEquals := ps.ServiceId == eps.ServiceId && ps.Addr == eps.Addr
				if isPidEquals && isPSEquals {
					isExists = true
					break
				}
			}
			//不存在，就删除
			if !isExists {
				delete(lastProcesses, key)
				dps = append(dps, eps)
			}

		}
		fn(nps, dps)
	}
}

var lastProcesses map[string]*handler.ServiceProcess

func init() {
	lastProcesses = make(map[string]*handler.ServiceProcess, 0)
}
